// http://dev.w3.org/2011/webrtc/editor/webrtc.html
// http://www.webrtc.org/interop

// http://habrahabr.ru/post/171477/

var statusBar = document.getElementById('sourceStatus');
var clientsCount = document.getElementById('remoteStatus');

var videoLocal = document.getElementById('sourcevid');
var videoRemote = document.getElementById('remotevid');

// action
var startvid = document.getElementById('start');
var connectvid = document.getElementById('connect');

var logg = function(s) { console.log(s); };

/***********************/

var webSocketServer = "ws://" + window.location.hostname + ":3000";
var peerConnectionConfiguration = { iceServers: [{ url: 'stun:stun.l.google.com:19302' }] };

var STATES = { WAITING: 'Waiting other client', IN_PROGRESS: 'Connection in progress...', CONNECTED: 'Connected', ERROR: 'Error', UNSUPPORTED: 'Your navigator is unsupported' };

/***********************/

var localStream;
var webSocket;
var peerConnection;

/***********************/

function setStatus(state){
  statusBar.innerHTML = state;
}

function clearContext(){
  videoRemote.src = '';

  if(webSocket){
    webSocket.close();
  }
  if(peerConnection){
    peerConnection.close();
  }

  webSocket = null;
  peerConnection = null;
}

/***********************/
// START VIDEO
function startVideo(){
  compatGetUserMedia({ audio: true, video: true }, onStartVideoSuccess, onStartVideoError);
}

function onStartVideoSuccess(stream){
  console.log("Local video started");

  localStream = stream;
  setStreamToElement(stream, videoLocal);
  videoLocal.play();

  //startNewConnection();
}

function onStartVideoError(){
  console.log("Cannot start video");
  setStatus(STATES.ERROR);
}

function onStreamLocalEnded(){
  console.log("Stream local ended");
  setStatus(STATES.ERROR);
}

/***********************/

function startNewConnection(){
  clearContext();

  webSocket = new WebSocket(webSocketServer);

  webSocket.onopen = onSocketOpen;
  webSocket.onerror = onSocketError;
  webSocket.onclose = onSocketClose;
  webSocket.onmessage = onSocketMessage;
}

// Waiting for another connect to server
function onSocketOpen(){
  console.log("Socket open");
  setStatus(STATES.WAITING);
}

// If connect error
function onSocketError(){
  console.log("Socket error");
  setStatus(STATES.ERROR);
}

// If connection is closed
function onSocketClose(){
  console.log("Socket close");
}
/*
  MESSAGE HERE
*/
function onSocketMessage(event){
  var message = JSON.parse(event.data);

  console.log("RECEIVE: " + event.data);

  if(message.type == 'do_call'){
    createPeerConnection();
    peerConnection.addStream(localStream);
    peerConnection.createOffer(onPeerConnectionCreateOfferSuccess, onPeerConnectionCreateOfferError);
  }else if(message.type == 'offer'){
    createPeerConnection();
    peerConnection.addStream(localStream);
    peerConnection.setRemoteDescription(compatRTCSessionDescription(message));
    peerConnection.createAnswer(onPeerConnectionCreateAnswerSuccess, onPeerConnectionCreateAnswerError, null);
  }else if(message.type == 'answer'){
    peerConnection.setRemoteDescription(compatRTCSessionDescription(message));
  }else if(message.type == 'candidate') {
    var candidate = compatRTCIceCandidate({
      sdpMLineIndex: message.sdpMLineIndex, 
      candidate: message.candidate,
      sdpMid: message.sdpMid
    });
    peerConnection.addIceCandidate(candidate);
  }else if(message.type == 'clients_count'){
    clientsCount.innerHTML = message.count;
  }

  // GROUP CHAT
  else if (message.type == 'chat'){
    /*
    var toF = "";
    // Get id of chat frame
    for (var i = 0; i < message.toUser.length; i++) {
      toF = toF + message.toUser[i];
    };
    
    // Each reciever
    for (var i = 0; i < message.toUser.length; i++) {
      if(from.innerHTML == message.toUser[i]) {
        
        /
        addChatMsg(message.fromUser, toF, message.color, message.data);
      }
    }
*/
    var from = message.fromUser;
    var to = message.toUser;
    var color = message.color;
    var data = message.data;
    /*
    var id = from + to;
    var  isActive = document.getElementById(id);
    // Neu nhu partner dong cua so chat
        
        if(isActive === null) {

          //Tao cua so chat moi
          createCF(id, from);
        } 
     */ 
    addMsg(from, to, color, data);
  }
  /*
  // entire message history
  else if (msg.type === 'history') {  
    console.log("data : " +msg.data);
    console.log("data length: " +msg.data.length);

    if(msg.data != null) {
          // insert every single message to the chat window
          for (var i=0; i < msg.data.length; i++) {

            // Parse content of each json in history to json
        var json = JSON.parse(msg.data[i].content);     

        // Neu la tin nhan
        if(json.type == 'chat') {
              addChatMsg(json.fromUser, 
                    json.fromUser,
                    json.color,
                    json.data
                    ); //new Date(json.data[i].time)
        }
          }
      }
  } */
  // Create chat frame
  else if(message.type === 'createCF') {
    
    var from1 = message.fromUser;
    var to1 = message.toUser;
    var id1 = from1 + to1;

    if($('#userName').html() === to1) {      
      createCF(id1, from1);
    }
  }
  else {
    console.log("Unknow message: " + message.type);
  }
}

/***********************/

function createPeerConnection(){
  console.log("createPeerConnection");
  setStatus(STATES.IN_PROGRESS);

  peerConnection = compatRTCPeerConnection(peerConnectionConfiguration);
  peerConnection.onicecandidate = onPeerConnectionIceCandidate;
  peerConnection.onaddstream = onPeerConnectionAddStream;
  peerConnection.onremovestream = onPeerConnectionRemoveStream;
}

function peerConnectionSendMessage(message) {
  var json = JSON.stringify(message);
  console.log("SEND: " + json);
  webSocket.send(json);
}

function onPeerConnectionIceCandidate(peerConnectionIceEvent){
  console.log("onPeerConnectionIceCandidate");
  if(peerConnectionIceEvent.candidate){
    peerConnectionSendMessage({
      type: 'candidate', 
      sdpMLineIndex: peerConnectionIceEvent.candidate.sdpMLineIndex,
      sdpMid: peerConnectionIceEvent.candidate.sdpMid,
      candidate: peerConnectionIceEvent.candidate.candidate
    });
  }
}

function onPeerConnectionAddStream(mediaStreamEvent){
  console.log("onPeerConnectionAddStream");
  setStreamToElement(mediaStreamEvent.stream, videoRemote);
  videoRemote.play();
  setStatus(STATES.CONNECTED);
}

function onPeerConnectionRemoveStream(mediaStreamEvent){
  console.log("onPeerConnectionRemoveStream");
}

function onPeerConnectionCreateOfferSuccess(sessionDescription){
  console.log("onPeerConnectionCreateOfferSuccess");
  peerConnection.setLocalDescription(sessionDescription);
  peerConnectionSendMessage(sessionDescription);
}

function onPeerConnectionCreateOfferError(error){
  console.log("onPeerConnectionCreateOfferError");
  setStatus(STATES.ERROR);
}

function onPeerConnectionCreateAnswerSuccess(sessionDescription){
  console.log("onPeerConnectionCreateAnswerSuccess");
  peerConnection.setLocalDescription(sessionDescription);
  peerConnectionSendMessage(sessionDescription);
}

function onPeerConnectionCreateAnswerError(error){
  console.log("onPeerConnectionCreateAnswerError");
  setStatus(STATES.ERROR);
}

/***********************/

function compatGetUserMedia(constraints, onStartVideoSuccess, onStartVideoError){
  if(navigator.webkitGetUserMedia){
    // Chrome
    navigator.webkitGetUserMedia(constraints, onStartVideoSuccess, onStartVideoError);
  }else if(navigator.mozGetUserMedia){
    // Firefox, need media.peerconnection.enabled = true
    navigator.mozGetUserMedia(constraints, onStartVideoSuccess, onStartVideoError);
  }else{
    console.log('Navigator unsupported: getUserMedia');
    setStatus(STATES.UNSUPPORTED);
  }
}

function setStreamToElement(stream, element){
  if(element.mozSrcObject){
    // Firefox
    element.mozSrcObject = stream;
  }else{
    element.src = URL.createObjectURL(stream);
  }
}

function compatRTCPeerConnection(peerConnectionConfiguration){
  if(typeof webkitRTCPeerConnection !== 'undefined'){
    // Chrome
    return new webkitRTCPeerConnection(peerConnectionConfiguration);
  }else if(typeof mozRTCPeerConnection !== 'undefined'){
    // Firefox
    return new mozRTCPeerConnection(peerConnectionConfiguration);
  }else{
    console.log('Navigator unsupported: RTCPeerConnection');
    setStatus(STATES.UNSUPPORTED);
    return null;
  }
}

function compatRTCSessionDescription(sessionDescription){
  if(typeof mozRTCSessionDescription !== 'undefined'){
    // Firefox
    return new mozRTCSessionDescription(sessionDescription);
  }else if(typeof RTCSessionDescription !== 'undefined'){
    // Chrome
    return new RTCSessionDescription(sessionDescription);
  }else{
    console.log('Navigator unsupported: RTCSessionDescription');
    setStatus(STATES.UNSUPPORTED);
    return null;
  }
}

function compatRTCIceCandidate(candidateInitDict){
  if(typeof mozRTCIceCandidate !== 'undefined'){
    // Firefox
    return new mozRTCIceCandidate(candidateInitDict);
  }else if(typeof RTCIceCandidate !== 'undefined'){
    // Chrome
    return new RTCIceCandidate(candidateInitDict);
  }else{
    console.log('Navigator unsupported: RTCIceCandidate');
    setStatus(STATES.UNSUPPORTED);
    return null;
  }
}

/*
  MESSAGE HERE
*/
function onChatMessage(event){
  var message = JSON.parse(event.data);

  console.log("RECEIVE: " + event.data);

  if (message.type == 'chat'){
    /*
    var toF = "";
    // Get id of chat frame
    for (var i = 0; i < message.toUser.length; i++) {
      toF = toF + message.toUser[i];
    };
    
    // Each reciever
    for (var i = 0; i < message.toUser.length; i++) {
      if(from.innerHTML == message.toUser[i]) {
        
        /
        addChatMsg(message.fromUser, toF, message.color, message.data);
      }
    }
*/
    var from = message.fromUser;
    var to = message.toUser;
    var color = message.color;
    var data = message.data;
    /*
    var id = from + to;
    var  isActive = document.getElementById(id);
    // Neu nhu partner dong cua so chat
        
        if(isActive === null) {

          //Tao cua so chat moi
          createCF(id, from);
        } 
     */ 
    addMsg(from, to, color, data);
  }
  /*
  // entire message history
  else if (msg.type === 'history') {  
    console.log("data : " +msg.data);
    console.log("data length: " +msg.data.length);

    if(msg.data != null) {
          // insert every single message to the chat window
          for (var i=0; i < msg.data.length; i++) {

            // Parse content of each json in history to json
        var json = JSON.parse(msg.data[i].content);     

        // Neu la tin nhan
        if(json.type == 'chat') {
              addChatMsg(json.fromUser, 
                    json.fromUser,
                    json.color,
                    json.data
                    ); //new Date(json.data[i].time)
        }
          }
      }
  } */
  // Create chat frame
  else if(message.type === 'createCF') {
    
    var from1 = message.fromUser;
    var to1 = message.toUser;
    var id1 = from1 + to1;

    if($('#userName').html() === to1) {      
      createCF(id1, from1);
    }
  }
  // List of clients
  else if(message.type == 'clients') {
    // clients i online
    var clients = message.data;

    for(var i in $('.fname').length) {
      alert($("li.fname:eq("+i+")").html());
    }
  }
  // HISTORY
  else if(message.type == 'history') {
    alert(message.data);
  }
  else {
    console.log("Unknow message: " + message.type);
  }
}

/***********************/

// Onload event
document.addEventListener('DOMContentLoaded', function (){
  statusBar = document.getElementById('sourceStatus');
  clientsCount = document.getElementById('remoteStatus');

  videoLocal = document.getElementById('sourcevid');
  videoRemote = document.getElementById('remotevid');

  // Start connection to websocket
  webSocket = new WebSocket(webSocketServer);
  webSocket.onmessage = onChatMessage;

  webSocket.onopen = function() {    
    var onl = $('#userName').html();
    // Send name to server
    sendMessage({
      type: 'clients', 
      data: onl
    });

    // Request history
    sendMessage({type: 'history'});
  }

  // Start video
  start.addEventListener('click', function() {
    startVideo();
  });

  // Connect to shared video
  connect.addEventListener('click', function() {
    startNewConnection();
  });
});

// MESSAGE
var from;
var to;
var msgContent; // Message content
var chatFrame;
var tos = new Array();

from = $("#userName").html();

function enterMsg() {
$('.inputField').keydown(function(event) { 
  
  //to = $(this).parent().parent().find('h3').html();
  // 2.
  to = $(this).parent().parent().attr("id");
  
  // Get each user who will recieve this message (When chat group)
  /*
  var j = to.indexOf(',');
  var i = 0;
  var toF = "";

  while (j != -1) {
    tos[i] = to.substring(i, j);
    to = to.substring(j + 1, to.length);
    j = to.indexOf(',');
    toF = toF + tos[i];
    i++;
  }

  // List of partner
  tos[i] = to.substring(1, to.length);
  toF = toF + tos[i];
  alert(toF);
  return;
  */

  // Lay ten nguoi kia
  //var to = $(this).parent().parent().find('.to').html();

  // Set id cho Frame chat
 // $(this).parent().prev().removeAttr("id");
  //$(this).parent().prev().prop('id', "CF"+ toF);

  // Set Farmw cho input.
  //$(this).removeAttr("id");
  //$(this).prop('id', toF);
   
  
  // Content of message
  //msgContent = document.getElementById(to);
  //msgContent = document.getElementById(toF);


  // When user press Enter key window.event.keyCode
  if(event.which == 13){

    var content = $(this).val();
    
    // Message content is empty.
    if(content == ""){
      return;
    }
    console.log("msg will be sent -> " + content);
    // Add to chat frame
    //addMsg("Me", to, "black", content);

    //Send this message to server.
    sendMessage({
      type: "chat",
      fromUser: from,
      toUser: to,
      data: content,
      color: "green"
    });
    
    $(this).val("");
  }
});
}

// send the message to websocket server
function sendMessage(message) {
  
  //Chuyen mesage sang kieu JSON
  var mymsg = JSON.stringify(message);
  logg("SEND: " + mymsg);
  //Goi message den websocket server.
  
  webSocket.send(mymsg);
}

// Add mesage into chat frame.
function addChatMsg(fromUser, toUser, color, msg){

  console.log(fromUser+" "+toUser+" "+color+" "+msg);
  chatFrame = document.getElementById("CF" + toUser);
  console.log(chatFrame);
  var msgP = document.createElement("p");

  msgP.innerHTML = '<span style="color:'+color+'">'+fromUser+ ' : '+msg+'</span>'
  
  chatFrame.appendChild(msgP);
  console.log("Add thanh cong");
  //Tu dong cuon len
}

// Add mesage into chat frame.
function addMsg(fromUser, frame, color, msg){

  var frameMsg = $("#" + frame).find(".mainCF");
  
  var msgP = document.createElement("p");
  var content = emoticons(msg);
  msgP.innerHTML = '<span style="color:'+color+'">'+fromUser+ ' : '+content+'</span>'
  
  frameMsg.append(msgP);
  console.log("Add thanh cong");
  //Tu dong cuon len

  $(".mainCF").animate({
     scrollTop: $(".mainCF")[0].scrollHeight
  }, 1000);
}

// Create chat frame
$('.sms').click(function () {
  
  // Create in recent page
  var from = $('#userName').html();
  var to = $(this).parent().parent().find('.fname').html();
  var id = from + to;
  
  createCF(id, to);

  // Create in the partner page
  console.log("msg will be sent to " + to);

  // Goi message len websocket.
  sendMessage({
    type: "createCF",
    fromUser: from,
    toUser: to
  });

  
    // Request history
    sendMessage({type: 'history'});
});

function createCF(id, to) {
  // Create in recent page
  /*
  var isVisible = document.getElementById(id);

  if(isVisible == null) {
    $('.template').first().prop("id", id);
    $('.template').first().find('.to').html(to);
    $('.template').first().show();
    $('.template').first().removeClass('template');
  } else {
    return false;
  }
*/
  var isVisible = document.getElementById(id);
  if(isVisible != null) { return; }

  //
  var c_frame = '';
  c_frame += '<li class="template chatFrame" id="' +id+ '">';
  c_frame += '<div class="headCF">';
  c_frame += '<h3 class="to">' +to+ '</h3>';
  c_frame += '<button class="CloseCF"></button>';
  c_frame += '</div>';
  c_frame += '<div class="mainCF"></div>';
  c_frame += '<div class="emo-box">';
  c_frame += '<ul class="all-emotioncs">';
  c_frame += '<li><img src="images/smiles/smile.png" id=":)" class="img-emotions" title=":)"></li>';
  c_frame += '<li><img src="images/smiles/haha.png" id=":D" class="img-emotions" title=":D"></li>';
  c_frame += '<li><img src="images/smiles/adore.png" id="o.o" class="img-emotions" title="o.o"></li>';
  c_frame += '<li><img src="images/smiles/grimace.png" id=":p" class="img-emotions" title=":p"></li>';
  c_frame += '<li><img src="images/smiles/misdoubt.png" id=":o" class="img-emotions" title=":o"></li>';
  c_frame += '<li><img src="images/smiles/what.png" id=":?" class="img-emotions" title=":?"></li>';
  c_frame += '<li><img src="images/smiles/cool.png" id="8-)" class="img-emotions" title="8-)"></li>';
  c_frame += '<li><img src="images/smiles/sleep.png" id="zzz" class="img-emotions" title="zzz"></li>';
  c_frame += '<li><img src="images/smiles/angry.png" id="><" class="img-emotions" title="><"></li>';
  c_frame += '<li><img src="images/smiles/cry.png" id=":((" class="img-emotions" title=":(("></li>';
  c_frame += '<li><img src="images/smiles/nothing_to_say.png" id=":|" class="img-emotions" title=":|"></li>';
  c_frame += '<li><img src="images/smiles/sad.png" id=":(" class="img-emotions" title=":("></li>';
  c_frame += '<li><img src="images/smiles/stop.png" id=":x" class="img-emotions" title=":x"></li>';
  c_frame += '</ul>';
  c_frame += '<button class="down"></button>';
  c_frame += '</div>';
  c_frame += '<div class="messageCF">';
  c_frame += '<input type="text" name = "inputText" class="inputField" placeholder = "Write your message here ..." >';
  c_frame += '<button class="show-emo"></button>';
  c_frame += '</div>';
  c_frame += '</li>';
  
  $('ul#FrameChatList').append(c_frame);
  
  enterMsg();
  // Action in chat frame
  chatFrameAction();
}

// Action in chat frame
function chatFrameAction() {
  // Enable drag element
      $('.template').draggable({snap: true});
      
      // Close a chat frame
      $('.CloseCF').click(function() {
        $(this).parent().parent().remove();
      });

      // Show hide emotion
      $('.show-emo'). click(function() {
        $(this).parent().parent().find('.emo-box').toggle();
      });

      // Get content of emotion
      $('.img-emotions').click(function() {
        
        var emo = $(this).attr('id');
        $(this).parent().parent().parent().next().find('.inputField').val(emo);
      });
}

// EMONTION
function emoticons(text){
    // The base URL of all our smilies
    var url = "images/smiles/";

    // A regex alternation that looks for all of them (be careful to use escapes
    // where necessary)
    var searchFor = /:D|:-D|:\)|:-\)|;\)|';-\)|:\(|:-\(|:o|:\?|8-\)|:x|:P|:\(\(|:\||><|zzz|o.o/gi;

    // A map mapping each smiley to its image
    var map = {
        ":D"  : 'haha.png', // Capped version of the next
        ":d"  : 'haha.png', // Lower case version of the previous
        "o.o" : 'adore.png', // Capped version of the next
        "O.O" : 'adore.png', // Lower case version of the previous
        ":)"  : 'smile.png',
        ":P" : 'grimace.png',
        ":p" : 'grimace.png',

        ":O"  : 'misdoubt.png', // Capped version of the next
        ":o"  : 'misdoubt.png', // Lower case version of the previous
        ":?"  : 'what.png',
        "8-)" : 'cool.png',

        ":X"  : 'stop.png',    // Capped version of the next
        ":x"  : 'stop.png',    // Lower case version of the previous
        "zzz"  : 'sleep.png',   // Capped version of the next
        ":(("  : 'cry.png',
        "><" : 'angry.png',
        ":|" : 'nothing_to_say.png',
        ":("  : 'sad.png'    // Lower case version of the previous
    };

    // Do the replacements
    text = text.replace(searchFor, function(match) {
        var rep;

        // Look up this match to see if we have an image for it
        rep = map[match];

        // If we do, return an `img` tag using that smiley icon; if not, there's
        // a mis-match between our `searchFor` regex and our map of
        // smilies, but handle it gracefully by returning the match unchanged.
        return rep ? '<img src="' + url + rep + '" class="emoticons" />' : match;
    });

    return (text);
}